#ifndef YOOHOO_XMPPCORE_XMPPPARSINGFACTORY_H
#define YOOHOO_XMPPCORE_XMPPPARSINGFACTORY_H

#include "xmppcore/xmppparserfactory.h"
#include "xmppcore/xmppelement.h"

#include <QtCore/QHash>
#include <QtCore/QReadWriteLock>

class QXmlStreamReader;

namespace yoohoo_xmppcore {

class Stanza;
class StanzaError;

class YOOHOO_XMPPCORE_EXPORT XmppParsingFactory {

class ParsingHierarchy;

public:
	static const QString NAMESPACE_STREAM;

	XmppParsingFactory();
	~XmppParsingFactory();
	XmppElement* parse(QString xml, bool stream = false);
	void registerParser(XmppParserFactory* parserFactory, ProtocolRelation relation);
	void registerParser(XmppParserFactory* parserFactory, ProtocolRelations relations);
	void unregisterParser(XmppParserFactory* parserFactory);
	void setDebug(bool debug);
	bool debug();

protected:
	XmppObject* parseProtocol(QXmlStreamReader* reader, QString& xml, ProtocolKey enclosing);
	QList<ParsingAttribute> readAttributes(QXmlStreamReader* reader);
	bool parseStanza(QXmlStreamReader* reader, QString& xml, QString& localName, QString& namespaceUri,
			ParsingHierarchy& hierarchy, XmppParser* parser);
	bool parseChildElement(QXmlStreamReader* reader, QString& xml, const QString& name, const QString& namespaceUri,
		ParsingHierarchy* hierarchy, XmppParser* parser);
	bool parseElement(QXmlStreamReader* reader, QString& xml, ParsingHierarchy& hierarchy,
		const QString& currentNamespace, XmppParser* parser);

private:
	XmppParserFactory* findParserFactory(QString& localName, QString& namespaceUri);
	bool readStanzaAttributes(ParsingHierarchy& hierarchy, QXmlStreamReader* reader, XmppParser* parser);
	void cleanParsingEnv(XmppParser* parser);

private:
	QHash<ProtocolKey, XmppParserFactory*> _parserFactories;
	QSet<ProtocolRelation> _protocolRelations;
	QHash<ProtocolKey, ProtocolRelations> _protocolKeyAndRelations;
	QReadWriteLock _lock;
	bool _debug;

class ParsingHierarchy {
public:
	ParsingHierarchy(QString localName = QString(), ParsingHierarchy* parent = 0);
	void setParent(ParsingHierarchy* parent);
	const QString& localName() const;
	QString toString();

private:
	QString _localName;
	bool _changed;
	ParsingHierarchy* _parent;
	QString _path;
};

};

}

#include "xmppcore/predefinedxmppparsingfactory.h"

#endif
